// Test for displaying text to the 104x48 monochrome display.

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <ft2build.h>
#include FT_FREETYPE_H

static FT_Library ft_library;
static FT_Face ft_face;

static char* fontfile = "10-Fixed.bdf";
static char fb[104*48/8];
static int ftfd;
static char* fbp;

void setup_fb()
{
  ftfd = open("/dev/freshtel0", O_RDWR);
  if(ftfd == -1)
  {
    perror("Cannot open freshtel device");
    exit(1);
  }

  fbp = (char *)mmap(0, sizeof(fb), PROT_READ|PROT_WRITE, MAP_SHARED, ftfd, 0);
  if ((long)fbp == -1)
  {
    perror("Failed to map framebuffer device to memory");
    exit(1);
  }
}

void refresh_fb()
{
  memcpy(fbp, fb, sizeof(fb));
  ioctl(ftfd, /*FRESHTEL_IOCUPDATE*/ 1, NULL);
}

void set_pixel_fb(int x, int y, int on)
{
  int pos;
  int bit;

  if (y >= 48 || x >= 104 || y < 0 || x < 0)
  {
    printf("bad pixel coords (%d,%d)\n", x, y);
  }

  pos = (y * 104 +  x) / 8;
  bit = (y * 104 +  x) % 8;
  if (on)
  {
    fb[pos] |= (0x80 >> bit);
  }
  else
  {
    fb[pos] &= ~(0x80 >> bit);
  }
}

static void add_glyph_to_screen(FT_Bitmap* bitmap)
{
  static int rowPos = 0;
  static int colPos = 0;
  int x;
  int y;
  int pixel = 0;
  int set;

  if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO)
  {
    // Copy the glyph into place.
    for (y = 0; y < bitmap->rows; y++)
    {
      for (x = 0; x < bitmap->width; x++)
      {
	set = bitmap->buffer[((y * bitmap->width) + x) / 8] & (0x80 >> (x % 8));
	set_pixel_fb(rowPos + x, colPos + y, set);

        pixel++;
      }
    }

    // Set position for next glyph
    rowPos += bitmap->width;
    if (rowPos >= 104 - bitmap->width)
    {
      rowPos = 0;
      colPos += bitmap->rows + 2;
      if (colPos >= 48 - bitmap->rows)
      {
	colPos = 0;
	refresh_fb();
	usleep(500000);
	memset(fb, 0, sizeof(fb));
      }
    }
  }
  else
  {
    fprintf(stderr, "invalid pixel mode: %d\n", bitmap->pixel_mode);
    exit(9);
  }
}

int main(int argc, char** argv)
{
  int error;
  int i;

  memset(fb, 0, sizeof(fb));
  setup_fb();
  refresh_fb();

  error = FT_Init_FreeType(&ft_library);
  if (error)
  {
    return 2;
  }

  error = FT_New_Face(ft_library, fontfile, 0, &ft_face);
  if (error == FT_Err_Unknown_File_Format)
  {
    fprintf(stderr, "invalid font file: %s\n", fontfile);
    return 3;
  }
  else if (error)
  {
    fprintf(stderr, "can't open font file: %s\n", fontfile);
    return 3;
  }
  

  error = FT_Set_Pixel_Sizes(ft_face, 0, 10); 
  if (error)
  {
    fprintf(stderr, "can't set pixel size of 16\n");
    return 4;
  }

  //glyph_index = FT_Get_Char_Index( ft_face, charcode );
  for (i = 0; i < ft_face->num_glyphs; ++i)
  {
    error = FT_Load_Glyph(ft_face, i, 0);
    if (error)
    {
      fprintf(stderr, "can't load glyph: %i\n", i);
    }
    else
    {
      error = FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_MONO);
      if (error)
      {
	fprintf(stderr, "can't render glyph: %i\n", i);
      }
      else
      {
	add_glyph_to_screen(&ft_face->glyph->bitmap);
      }
    }
  }

  return 0;
}
